import { useFrame, useThree } from "@react-three/fiber";
import { useSphere } from "@react-three/cannon";
import { useRef, useEffect, useState } from "react";
import { Vector3, Euler, Raycaster } from "three";
import { useKeyboard } from "../hooks/useKeyboard";
import { FPV } from "./FPV";
import { TPV } from "./TPV";
import { useStore } from "../hooks/useStore";

const JUMP_FORCE = 3;
const SPEED = 3;

export const Player = () => {
  const { moveBackward, moveForward, moveRight, moveLeft, jump, toggleView } =
    useKeyboard();
  const [isThirdPerson, setThirdPerson] = useStore(state => [
    state.isThirdPerson,
    state.setThirdPerson
  ]);
  const { camera } = useThree();
  const [ref, api] = useSphere(() => ({
    mass: 1,
    type: "Dynamic",
    position: [0, 2, 0],
  }));
  
  // 创建玩家模型的引用
  const playerModelRef = useRef();
  
  const vel = useRef([0, 0, 0]);
  useEffect(() => {
    api.velocity.subscribe((v) => (vel.current = v));
  }, [api.velocity]);
  
  const pos = useRef([0, 0, 0]);
  useEffect(() => {
    api.position.subscribe((p) => (pos.current = p));
  }, [api.position]);
  
  // 监听视角切换键
  useEffect(() => {
    if (toggleView) {
      const newState = !isThirdPerson;
      setThirdPerson(newState);
    }
  }, [toggleView, setThirdPerson]);
  
  // 存储玩家位置向量
  const playerPosition = useRef(new Vector3());
  
  // 存储TPV返回的摄像机旋转
  const tpvRotation = useRef(new Euler());
  
  // TPV组件的引用
  const tpvRef = useRef(null);
  
  // 添加射线检测器
  const raycaster = useRef(new Raycaster());
  
  // 添加全局状态
  const [addCube, removeCube] = useStore((state) => [
    state.addCube,
    state.removeCube,
  ]);
  
  useFrame(() => {
    // 更新玩家位置向量
    playerPosition.current.set(
      pos.current[0],
      pos.current[1],
      pos.current[2]
    );
    
    // 更新玩家模型位置
    if (playerModelRef.current) {
      playerModelRef.current.position.copy(playerPosition.current);
    }
    
    // 第一人称视角下更新相机位置
    if (!isThirdPerson) {
      camera.position.copy(playerPosition.current);
    }
    // 第三人称视角下，从ref获取旋转
    else if (tpvRef.current) {
      tpvRotation.current.copy(tpvRef.current.getRotation());
    }
    
    const direction = new Vector3();

    const frontVector = new Vector3(
      0,
      0,
      (moveBackward ? 1 : 0) - (moveForward ? 1 : 0)
    );

    const sideVector = new Vector3(
      (moveLeft ? 1 : 0) - (moveRight ? 1 : 0),
      0,
      0
    );

    direction
      .subVectors(frontVector, sideVector)
      .normalize()
      .multiplyScalar(SPEED);
    
    // 根据当前视角模式应用不同的旋转
    if (isThirdPerson) {
      // 在第三人称模式下，移动方向应该跟随相机的水平旋转
      direction.applyEuler(tpvRotation.current);
    } else {
      // 第一人称模式保持原样
      direction.applyEuler(camera.rotation);
    }

    api.velocity.set(direction.x, vel.current[1], direction.z);
    
    if (jump && Math.abs(vel.current[1]) <= 0.05) {
      api.velocity.set(vel.current[0], JUMP_FORCE, vel.current[2]);
    }
  });

  // 添加处理第三人称放置方块的方法
  const handleThirdPersonCubeOperation = (e) => {
    if (!isThirdPerson || !tpvRef.current) return false;
    
    // 获取相机方向和目标位置
    const cameraDirection = tpvRef.current.getCameraDirection();
    
    // 设置射线检测器
    raycaster.current.set(camera.position, cameraDirection);
    
    // 使用假射线进行简单的检测
    const distance = 10; // 最大检测距离
    const endPoint = new Vector3().copy(camera.position).add(
      cameraDirection.clone().multiplyScalar(distance)
    );
    
    // 获取所有方块位置
    const cubes = useStore.getState().cubes;
    
    // 简化的检测算法
    let closestCube = null;
    let closestDistance = Infinity;
    let closestFace = -1;
    
    cubes.forEach(cube => {
      const cubePos = new Vector3(...cube.pos);
      // 检查每个方块的六个面
      for (let face = 0; face < 6; face++) {
        // 根据面的索引确定面的中心位置
        const faceCenter = cubePos.clone();
        if (face === 0) faceCenter.x += 0.5; // +x面
        else if (face === 1) faceCenter.x -= 0.5; // -x面
        else if (face === 2) faceCenter.y += 0.5; // +y面
        else if (face === 3) faceCenter.y -= 0.5; // -y面
        else if (face === 4) faceCenter.z += 0.5; // +z面
        else if (face === 5) faceCenter.z -= 0.5; // -z面
        
        // 计算射线到面中心的距离
        const distanceToFace = faceCenter.distanceTo(camera.position);
        
        // 检查面是否在射线方向上
        const directionToFace = faceCenter.clone().sub(camera.position).normalize();
        const dotProduct = directionToFace.dot(cameraDirection);
        
        // 如果面在射线前方并且比之前找到的更近，则更新
        if (dotProduct > 0.7 && distanceToFace < closestDistance) {
          closestCube = cube;
          closestDistance = distanceToFace;
          closestFace = face;
        }
      }
    });
    
    // 如果找到了方块
    if (closestCube && closestDistance < distance) {
      const [x, y, z] = closestCube.pos;
      
      // 根据鼠标按键和点击的面来添加或删除方块
      if (e.button === 2) {
        removeCube(x, y, z);
      } else {
        if (closestFace === 0) addCube(x + 1, y, z);
        else if (closestFace === 1) addCube(x - 1, y, z);
        else if (closestFace === 2) addCube(x, y + 1, z);
        else if (closestFace === 3) addCube(x, y - 1, z);
        else if (closestFace === 4) addCube(x, y, z + 1);
        else if (closestFace === 5) addCube(x, y, z - 1);
      }
      
      return true; // 表示已处理
    }
    
    return false; // 未处理
  };
  
  // 添加鼠标点击事件监听
  useEffect(() => {
    const onMouseClick = (e) => {
      if (isThirdPerson) {
        handleThirdPersonCubeOperation(e);
      }
    };
    
    window.addEventListener('mousedown', onMouseClick);
    return () => {
      window.removeEventListener('mousedown', onMouseClick);
    };
  }, [isThirdPerson]);

  return (
    <>
      <mesh ref={ref}></mesh>
      {/* 第三人称玩家模型 - 一个1x1x1的方块 */}
      <mesh 
        ref={playerModelRef} 
        visible={isThirdPerson} // 仅在第三人称模式下可见
      >
        <boxGeometry args={[1, 1, 1]} />
        <meshStandardMaterial color="blue" />
      </mesh>
      
      {/* 条件渲染FPV或TPV组件 */}
      {isThirdPerson ? (
        <TPV 
          ref={tpvRef}
          isThirdPerson={isThirdPerson}
          playerPosition={playerPosition.current}
        />
      ) : (
        <FPV />
      )}
    </>
  );
};
